<?php if(!defined('PUBLIC_DIR')) die('No Access!');
using('System.Data.Security');
using('System.Web');
using('System.Web.MVC');

Cnamespace('System');
class App{
	private static $Application;
	private static $Config;
	
	public static $Request;
	public static $Response;

	public static $Log;

	public static $Router;
	public static $User;

	public static function App_AutoLoad($_className){
		$_fileName = $_className;
		if(strpos($_fileName, "System\\") === 0)
			$_fileName = str_replace("System", basename(SYSTEM_DIR), $_fileName);
		if(is_file($path = (dirname(SYSTEM_DIR) . DS . str_replace('\\', DS, $_fileName . '.inc.php')))){
			require_once($path);
			if(!class_exists($_className))
				class_alias(basename($path, '.inc.php'), $_className);
		}else{
			foreach(AutoLoad::$Paths as $alDir){
				if(is_file($path = ($alDir . DS . $_className . '.inc.php')))
					require_once($path);
			}
		}
	}
	
	public static function Create(){
		if(self::$Application == null)
			return self::$Application = new App();
	}

	public static function Config(){
		if(self::$Config == null)
			return self::$Config = new Config();
		else
			return self::$Config;
	}
	
	public static function Run($runType = 'production'){
		if(strpos($runType, 'dev') !== false && strpos($runType, 'dev') == 0)
			define('DEV', true);
		if(self::$Application != null){
			$event = new Event('App.PreInit');
			self::$Application->PreInit();
			$event->Invoke();
			$event = new Event('App.Init');
			self::$Application->Init();
			$event->Invoke();
			$event = new Event('App.Load');
			self::$Application->Load();
			$event->Invoke();
			$event = new Event('App.LoadComplete');
			self::$Application->LoadComplete();
			$event->Invoke();
			$event = new Event('App.PreRender');
			self::$Application->PreRender();
			$event->Invoke();
			$event = new Event('App.Unload');
			$event->Invoke();
			self::$Application->Unload();
		}else
			trigger_error('Brak obiektu aplikacji! Prawdopodobnie został usunięty.', E_USER_ERROR);
	}

	public function App(){
		/*
		Ustawiane jest Request, Response, IsPostBack, UICulture.
		*/
		self::$Application = $this;
		self::$Request = new Request();
		self::$Response = new Response();
		//self::$Request->IsPostBack ->> move to Request
		//self::$Request->UICulture ->> move to Request

		//Too long
		self::$Router = new Router(self::$Request);
	}

	private function PreInit(){
		/*
		Tu można dynamicznie tworzyć kontrolki.
		Obiekty kontrolek są już powołane do życia, więc można podłączać się do zdarzeń, które występują w kontrolkach.
		Ustawianie stron wzorcowych, skórek (Theme).
		Odczyt danych profilu użytkownika.
		W przypadku korzystania z Templated User Control należy w tym zdarzeniu utworzyć instancję kontenera nazw i połączyć go z layoutem.
		*/
		self::$Router->RegisterEvents();
		
		self::$User = new User();

		if(!is_dir(App::Config()->cache_system_path))
			mkdir(App::Config()->cache_system_path);
	}

	private function Init(){
		/*
		Tworzone są puste kontrolki i ich hierarchia.
		*/	
	}

	private function Load(){
		/*
		Kontrolki przywracane są z zapisanego stanu (ViewState), jeżeli jest to wywołanie zwrotne.
		ClientScriptManager i rejestracja nowych skryptów.
		Można wykonywać dodatkową. inicjalizację kontrolek
		Uwaga: kontrolki, powiązane ze źródłem danych nie są jeszcze wypełnione treścią.
		*******************************************************************************************
		Wywoływane jest Validate() dla kontrolek i ustawione zostaje IsValid.
		*******************************************************************************************
		Obsługiwane są tutaj zdarzenia kontrolek, np. kliknięcia przycisków.
		*/
	}

	private function LoadComplete(){
		/*
		Zakończony jest etap ładowania.
		*/
	}

	private function PreRender(){
		/*
		Można nanieść ostateczne poprawki do wyglądu kontrolek.
		*******************************************************************************************
		Kontrolki wpisują swoje dane do odpowiedzi.
		Ustawianie zaznaczonego elementu.
		*/
	}

	private function Unload(){
		/*
		Zwolnienie zasobów.
		Można zapisywać do logów i wykonywać tracing.
		Response/Request nie są dostępne.
		*/
		self::$Response->SendRespond();
		self::$Request = null;
		self::$Response = null;
		self::$Application = null;
	}
}